package dw2;
import java.awt.event.*;
import java.applet.*;
import java.awt.*;
import java.awt.color.ColorSpace;
import java.awt.image.BufferedImage;
import java.awt.image.ColorConvertOp;
import java.awt.image.ConvolveOp;
import java.awt.image.Kernel;
import java.awt.image.RescaleOp;
import java.io.File;
import java.io.IOException;
import java.util.*;
import java.util.logging.Level;
import java.util.logging.Logger;
import javax.sound.midi.InvalidMidiDataException;
import javax.sound.midi.MidiUnavailableException;

public class Main extends Applet implements Runnable, KeyListener
{    
    private static final long serialVersionUID = 1L;
    private Image toad_drive;
    private Image toad_dig;
    private Image toad_bomb;
    private Image toad_hurt;
    private Image rat_dig1;
    private Image rat_dig2;
    private Image rat_chase;
    private Image tankimg;
    private Image tankimg_fire;
    private Image tankimg_hurt;
    private Image groundimg;
    private Image skyimg;
    private Image segimg;
    private Image rider;
    private Image rider_fire;
    private Image rider_hurt;
    private Image newgunner;
    private Image newgunner_fire;
    private Image health_npc;
    private Image alienShip;
    private Image alienShip_death;
    private Image alienShip_hurt;
    private Image monster;
    private Image monster_fire;
    private Image monster_hurt;
    private Image alien;
    private Image alien_fire;
    private Image alien_hurt;
    private Image headimg;
    private Image[] bushes; 
    MediaTracker track;

    //SoundFX

    public AudioClip biteSound;
    public AudioClip playSound;
    public AudioClip bite1HardCrunch;
    public AudioClip bite6SoftNibble;
    public AudioClip bang;
    public AudioClip bigBang;
    public AudioClip toadHit;
    public AudioClip firstBlood;
    public AudioClip doubleKill;
    public AudioClip dominating;
    public AudioClip rampage;
    public AudioClip excellentSound;
    public AudioClip contraVictory;
    private boolean gameStarted = false;

    //private SoundFXMixer soundFX; to be made a class...
    
    //Music
    protected boolean toggleMusic = false;
    public MusicClient MC = new MusicClient();

    //Will be put into a Combo class...
    public int killCount = 0;
    public int comboCount = 0;
    public boolean comboMode = false;//Requires 10 kills in < 60 seconds, lasts 10 seconds

    public Worm player_1;
    public boolean summonToad = false;
    public boolean toadOnScreen = false;
    public boolean sandratOnScreen = false;
    public boolean sandRatCreated = false;
    public int bombCount = 0;
    private Random random = new Random();

    private Thread th;
    private int fps = 50;
    private boolean stopped = false;

    private Scenery ground;


    private long gameTime = fps*25;
    public int counts;
    private boolean paused = false;

    private boolean leftkey = false;
    private boolean rightkey = false;
    private boolean upkey = false;

    private boolean shaking = false;
    private int shakeamount = 5;
    private int scroll = 0;
    private int maxWidth=640*3;

    //added cycle 3
    public static final int numScores = 10;
    private String[] names;
    private int[] scores;
    Image quitImage;
    Image highscoreImage;

    //SET SCORE TO CHANGE LEVEL
    int levelScore_change = 1000;
    int boss_change = 3000;
    //int levelScore_change = 2500;
    //int boss_change = 5000;
    boolean clear = false;
    int numHPnpc = 0;
    boolean check = true;
    private boolean tryingToClear = false;

    private ArrayList<Particle> particles = new ArrayList<Particle>();
    private ArrayList<Bullet> bullets = new ArrayList<Bullet>();
    public ArrayList<NPC> npcs = new ArrayList<NPC>();

    Particle lastParticle = null; //will hold particle of boss death

    Scenery[] scene;


    Random rand = new Random();

    HUD hud;

    boolean running = false;

    //Menu Items
    MainMenu mainMenu;
    PauseMenu pauseMenu;
    HighscoreMenu hscoreMenu;
    Help helpMenu;
    GameOverMenu goMenu;
    GameOverMenu vicMenu;

    private int gameLevel;

    
    //HighScore
    XMLFileIO xio;
    static String highestScore;
    private int animal_count = 0;
    private int ratCount = 0;
    private boolean check2 = true;

    public Worm getPlayer1()
    {
        return player_1;
    }

    public boolean isShaking()
    {
        return shaking;
    }

    public void setShaking(boolean value)
    {
        shaking = value;
    }

    public int getMaxWidth()
    {
        return maxWidth;

    }

    public int getShakeAmount()
    {
        return shakeamount;
    }
    public void addBullet(Bullet newbullet)
    {
        bullets.add(newbullet);
    }
    public void addParticle(Particle newparticle)
    {
        particles.add(newparticle);
    }
    public int getScroll()
    {
        return scroll;
    }
    private long getMS()
    {
    	return new Date().getTime();
    }

    public void reset_game()
    {
        running = false;
        sandratOnScreen = false;
        player_1.reset_worm();
        npcs.clear();
        bullets.clear();
        particles.clear();
        gameTime = fps*25;
        counts = 0;
       
    }
    @Override
    public void init()
    {

        int track_id = 0;
        resize(800,600);
        bushes = new Image[5];
        hud = new HUD();
        scene  = new Scenery[10];
        
        track = new MediaTracker(this);
 
        //Initialize sounds
        bite1HardCrunch = getAudioClip( getDocumentBase(), "../Sounds/bite1 - hardCrunch.wav" );
        bite6SoftNibble = getAudioClip( getDocumentBase(), "../Sounds/bite6softNibble.wav" );
        bigBang = getAudioClip(getDocumentBase(), "../Sounds/sndBigBang.wav" );
        bang = getAudioClip(getDocumentBase(), "../Sounds/sndBang.wav" );
        playSound = getAudioClip( getDocumentBase(), "../Sounds/playUT.wav" );
        excellentSound = getAudioClip(getDocumentBase(), "../Sounds/excellentMK.wav" );
        firstBlood = getAudioClip(getDocumentBase(), "../Sounds/firstbloodUT.wav" );
        doubleKill = getAudioClip(getDocumentBase(), "../Sounds/doublekillUT.wav" );
        rampage = getAudioClip(getDocumentBase(), "../Sounds/rampageUT.wav" );
        dominating = getAudioClip(getDocumentBase(), "../Sounds/dominatingUT.wav" );
        contraVictory = getAudioClip(getDocumentBase(), "../Sounds/contraVictory.wav" );
        toadHit = getAudioClip(getDocumentBase(), "../Sounds/sndStone.wav" );

        headimg = getImage(getDocumentBase(), "../Images/Worm/head.png");
        segimg = getImage(getDocumentBase(), "../Images/Worm/segment.png");
        
        rider = getImage(getDocumentBase(), "../Images/NPC/camel_walking.png");
        rider_fire = getImage(getDocumentBase(), "../Images/NPC/camel_shooting.png");
        rider_hurt = getImage(getDocumentBase(), "../Images/NPC/camel_hurt.png");
        newgunner = getImage(getDocumentBase(), "../Images/NPC/gunner_walking.png");
        newgunner_fire = getImage(getDocumentBase(), "../Images/NPC/gunner_shooting.png");
        tankimg = getImage(getDocumentBase(), "../Images/NPC/tank_driving.png");
        tankimg_fire =  getImage(getDocumentBase(), "../Images/NPC/tank_firing.png");
        tankimg_hurt = getImage(getDocumentBase(), "../Images/NPC/tank_hurt.png");

        alienShip = getImage(getDocumentBase(), "../Images/NPC/ship01.png");
        alienShip_death = getImage(getDocumentBase(), "../Images/NPC/ship02.png");
        alienShip_hurt = getImage(getDocumentBase(), "../Images/NPC/ship03.png");
        health_npc = getImage(getDocumentBase(), "../Images/NPC/bird01.png");
        monster = getImage(getDocumentBase(), "../Images/NPC/monster01.png");
        monster_fire = getImage(getDocumentBase(), "../Images/NPC/monster02.png");
        monster_hurt = getImage(getDocumentBase(), "../Images/NPC/monster03.png");
        alien = getImage(getDocumentBase(), "../Images/NPC/alien01.png");
        alien_fire = getImage(getDocumentBase(), "../Images/NPC/alien02.png");
        alien_hurt = getImage(getDocumentBase(), "../Images/NPC/alien03.png");


        rat_dig1 =  getImage(getDocumentBase(), "../Images/NPC/rat_dig1.png");
        rat_dig2 =  getImage(getDocumentBase(), "../Images/NPC/rat_dig2.png");
        rat_chase = getImage(getDocumentBase(), "../Images/NPC/rat_chase.png");
        toad_drive = getImage(getDocumentBase(), "../Images/NPC/ToadDrive.png");
        toad_dig = getImage(getDocumentBase(), "../Images/NPC/ToadDig.png");
        toad_bomb = getImage(getDocumentBase(), "../Images/NPC/Bomb.png");
        toad_hurt = getImage(getDocumentBase(), "../Images/NPC/ToadDriveHurt.png");

        for(int x = 0;x<5;x++)
        bushes[x] = getImage(getDocumentBase(), "../Images/Background/bush"+(x+1)+".png");
        groundimg = getImage(getDocumentBase(),"../Images/Background/ground.png");
        skyimg = getImage(getDocumentBase(),"../Images/Background/sky.png");

        //added cycle 3
        highscoreImage = getImage(getDocumentBase(), "../Images/background_highscore.png");

        //changed cycle 2
        Image[] startMenuImages = new Image[4];
        startMenuImages[0] = getImage(getDocumentBase(), "../Images/background_img.jpg");
        startMenuImages[1] = getImage(getDocumentBase(), "../Images/b_play.png");
        startMenuImages[2] = getImage(getDocumentBase(), "../Images/b_highscores.png");
        startMenuImages[3] = getImage(getDocumentBase(), "../Images/b_help.png");

        //added cycle 2
        Image[] pauseMenuImages = new Image[5];
        pauseMenuImages[0] = getImage(getDocumentBase(), "../Images/b_resume.png");
        pauseMenuImages[1] = getImage(getDocumentBase(), "../Images/b_restart.png");
        pauseMenuImages[2] = startMenuImages[3];
        pauseMenuImages[3] = startMenuImages[2];
        pauseMenuImages[4] = getImage(getDocumentBase(), "../Images/b_quit.png");

        Image[] helpMenuImages = new Image[6];
        helpMenuImages[0] = getImage(getDocumentBase(), "../Images/help_objective.png");
        helpMenuImages[1] = getImage(getDocumentBase(), "../Images/help_controls.png");
        helpMenuImages[2] = getImage(getDocumentBase(), "../Images/left_arrow.png");
        helpMenuImages[3] = getImage(getDocumentBase(), "../Images/right_arrow.png");
        helpMenuImages[4] = getImage(getDocumentBase(), "../Images/b_return.png");
        helpMenuImages[5] = getImage(getDocumentBase(), "../Images/HelpBackground.png");

        Image[] gameOverImages = new Image[4];
        gameOverImages[0] = getImage(getDocumentBase(), "../Images/b_mainmenu.png");
        gameOverImages[1] = getImage(getDocumentBase(), "../Images/b_viewscores.png");
        gameOverImages[2] = getImage(getDocumentBase(), "../Images/b_savescore.png");
        gameOverImages[3] = getImage(getDocumentBase(), "../Images/gameover.png");

        Image[] victoryImages = new Image[4];
        victoryImages[0] = getImage(getDocumentBase(), "../Images/b_victory_mainmenu.png");
        victoryImages[1] = getImage(getDocumentBase(), "../Images/b_victory_viewscores.png");
        victoryImages[2] = getImage(getDocumentBase(), "../Images/b_victory_savescore.png");
        victoryImages[3] = getImage(getDocumentBase(), "../Images/background_highscore_confetti.png");


        track.addImage( tankimg,track_id++);
        track.addImage( headimg,track_id++);
        track.addImage( segimg,track_id++);
        track.addImage( rider,track_id++);
        track.addImage( newgunner,track_id++);
        track.addImage( newgunner_fire,track_id++);
        track.addImage(tankimg_fire,track_id++);
        track.addImage(tankimg_hurt,track_id++);
        track.addImage(rider_fire,track_id++);
        track.addImage(rider_hurt,track_id++);
        track.addImage(groundimg,track_id++);
        track.addImage(skyimg,track_id++);
        track.addImage(health_npc,track_id++);
        track.addImage(alienShip,track_id++);
        track.addImage(alienShip_death,track_id++);
        track.addImage(alienShip_hurt,track_id++);
        track.addImage(monster,track_id++);
        track.addImage(monster_fire,track_id++);
        track.addImage(monster_hurt,track_id++);
        track.addImage(alien,track_id++);
        track.addImage(alien_fire,track_id++);
        track.addImage(alien_hurt,track_id++);
        track.addImage(rat_dig1,track_id++);
        track.addImage(rat_dig2,track_id++);
        track.addImage(rat_chase,track_id++);
        track.addImage(toad_drive,track_id++);
        track.addImage(toad_dig,track_id++);
        track.addImage(toad_bomb,track_id++);
        track.addImage(toad_hurt,track_id++);

        //added cycle 3
        track.addImage(quitImage, track_id++);
        track.addImage(highscoreImage, track_id++);

        //added cycle 2
        for(int i = 0; i < startMenuImages.length; i++) {
            track.addImage(startMenuImages[i],track_id++);
        }

        for(int i = 0; i < pauseMenuImages.length; i++) {
            if(i != 2 && i != 3) //would be duplicates
                track.addImage(pauseMenuImages[i],track_id++);
        }

        for(int i = 0; i < gameOverImages.length; i++) {
            track.addImage(gameOverImages[i], track_id++);
        }

        for(int x =0;x<bushes.length;x++)
        {
            track.addImage(bushes[x],track_id++);
        }

        for(int i = 0; i < helpMenuImages.length; i++) {
            track.addImage(helpMenuImages[i],track_id++);
        }
        for(int i = 0; i< victoryImages.length; i++) {
            track.addImage(victoryImages[i], track_id++);
        }
        try
        {
            track.waitForAll();
        }
        catch(InterruptedException e)
        {
        }

        //NPC IMAGE LOADING
        Image[] npcrider_img = {rider, rider_fire,rider_hurt};
        npcRider.initImage(npcrider_img);

        Image[] npctank_img = {tankimg, tankimg_fire,tankimg_hurt};
        npcTank.initImage(npctank_img);

        Image[] npcgunner_img = {newgunner, newgunner_fire};
        npcPeople.initImage(npcgunner_img);

        Image[] npcAnimals_img = {health_npc};
        npcAnimals.initImage(npcAnimals_img);
        
        Image[] npcsandrat_img = {rat_dig1, rat_dig2, rat_chase};
        npcSandrat.initImage(npcsandrat_img);

        Image[] npctoad_img = {toad_drive, toad_dig, toad_hurt};
        npcToad.initImage(npctoad_img);

        Image[] bomb_img = {toad_bomb};
        Bomb.initImage(bomb_img);

        Image[] npcAlienShip_img = {alienShip,alienShip_death,alienShip_hurt};
        npcAlienShip.initImage(npcAlienShip_img);

        Image[] monster_img = {monster,monster_fire,monster_hurt};
        npcMonster.initImage(monster_img);

        Image[] alien_img = {alien,alien_fire,alien_hurt};
        npcAlien.initImage(alien_img);

        //Main Menu Setup
        mainMenu = new MainMenu(this, startMenuImages);
        mainMenu.init();
        setLayout(new BorderLayout());     
        add(mainMenu);
        pauseMenu = new PauseMenu(this, pauseMenuImages);
        pauseMenu.init();


        //added cycle 3

        File highscores = new File("highscores.xml");
        
        xio = new XMLFileIO(highscores);
        if(!highscores.exists()) {
            names = new String[numScores];
            scores = new int[numScores];
            for(int i = 0; i < numScores; i++) {
                names[i] = "AAA";
                scores[i] = 10 - i;
            }
            xio.write(names, scores);
        }
        xio.read();
        String[][] userScores = xio.getUserListasString();
        highestScore = userScores[1][0];
        hscoreMenu = new HighscoreMenu(this, highscoreImage, userScores[0], userScores[1], helpMenuImages[4]);
        hscoreMenu.init();


        helpMenu = new Help(this, helpMenuImages);
        helpMenu.init();

        goMenu = new GameOverMenu(false, this, gameOverImages);
        goMenu.init();

        vicMenu = new GameOverMenu(true, this, victoryImages);
        vicMenu.init();
        vicMenu.setBG();

        Random num = new Random();

        for(int i = 0; i < scene.length; i++)
        {
            Image temp = bushes[num.nextInt(bushes.length)];
            scene[i] = new Scenery(temp,rand.nextInt(maxWidth),(getSize().height/2)-temp.getHeight(this));
        }

        ground = new Scenery(groundimg,0,300);
        player_1 = new Worm(headimg,segimg, this);

    
        setBackground(new Color(0,255,255));
  
        addKeyListener(this);

//        MC.playMenuMusic(0);

    }

    public void removeNPC(NPC removednpc)
    {
        npcs.remove(npcs.indexOf(removednpc));
        counts--;
        if(removednpc instanceof npcToad) {
            //When this particle is no longer in the particl arraylist,
            //the game will end. This way, the player gets to see the boss' death
            lastParticle = ((npcToad) removednpc).particles[0];
        }
    }

    public void removeParticle(Particle removedparticle)
    {
        particles.remove(particles.indexOf(removedparticle));
    }
    public void removeBullet(Bullet removedbullet)
    {
        bullets.remove(bullets.indexOf(removedbullet));
    }
    @Override
    public void start()
    {
        if (th == null)
        {
        
          if(MC.isActive() == true)
            MC.play();
          th = new Thread(this);
          th.start();
        }
    }

    @Override
    public void stop()
    {
        if (th != null)
        {
           
          if(MC.isActive() == true)
            MC.pause();
            th.stop();
            th = null;
        }
       // stopped = true;
    }

    @Override
    public void destroy()
    {
        stopped = true;
    }

    public void run()
    {           
        while(!stopped)
        {
            if(running == false) continue;

            if(!gameStarted) {
                playSound.play();
                gameStarted = true;
            }
            // increases the tempo of the midi playback when damaged

            if(player_1.getHP() < 20 && player_1.getHP() >= 10) {
                MC.dangerTempo(1.5);
            }

            if(player_1.getHP() < 10) {
                MC.dangerTempo(2.0);
            }

//            if(MC.getTempo() > 1.0) {
//                if(player_1.getHP() > 25) {
//                    MC.normalTempo();
//                }
//            }

            //added cycle 3, displays highscores at end of game

      
            if(player_1.getHP() <= 0) {
                running = false;
                MC.stopMusic();
                MC.playMenuMusic(1);
                boolean hscore = hscoreMenu.evaluateScore(player_1.getScore());
                goMenu.achievedHighscoreButton(hscore);
                goMenu.setBG();
                add(goMenu);
                validate();
                repaint();
                reset_game();
            }

            if(lastParticle != null && !particles.contains(lastParticle)) {
                lastParticle = null;
                running = false;
                MC.stopMusic();
               // MC.playMenuMusic(1);
                contraVictory.play();
                boolean hscore = hscoreMenu.evaluateScore(player_1.getScore());
                vicMenu.achievedHighscoreButton(hscore);
                add(vicMenu);
                validate();
                repaint();
                reset_game();
            }

            Point worm_head_pos = player_1.getHeadPosition();
            int seconds = (int)(gameTime/fps);
            if(paused){continue;}

            gameTime ++;
            scroll = worm_head_pos.x;

            if(scroll < getSize().width/2)
                scroll = getSize().width/2;
            if(scroll > maxWidth-getSize().width/2)
                scroll = maxWidth-getSize().width/2;


            //Level Decider//
            
            if(player_1.getScore() < levelScore_change){
                gameLevel = 1;
                
                //Test alien: Aliens spawn first
                //gameLevel = 3;
                //clear = true;

            }

            //Change to Level 2
            if(player_1.getScore() > levelScore_change && check){
                gameLevel = 2;          //sets which level is next
                tryingToClear = true;   //tells level independent npcs to stop making   
                if(counts == 0){
                    //System.out.println("LEVEL UP");
                    clear = true;
                    hud.levelUp();
                    check = false;
                    tryingToClear = false;
                    player_1.comboManager.excellentSound.play();
                    seconds = 0;
                    System.out.println(seconds);
                }
            }
            //Change to Boss
            if(player_1.getScore() > boss_change && check2){
                gameLevel = 3;          //sets which level is next
                tryingToClear = true;   //tells level independent npcs to stop making
                if(counts == 0){
                    //System.out.println("LEVEL UP");
                    clear = true;
                    hud.levelUp();
                    check = false;
                    tryingToClear = false;
                    player_1.comboManager.excellentSound.play();
                    seconds = 0;
                    //System.out.println(seconds);
                }

            }


            if((gameLevel == 3 && clear && !tryingToClear ) || summonToad) {
                 //TOAD TEST
                if(!toadOnScreen) {
                    npcs.add(new npcToad(-64,(getSize().height/2),0,100));
                    toadOnScreen = true;
                    summonToad = false;
                    counts++;
                    MC.stopMusic();
                    MC.playSpecialMusic();
                    MC.play();
           }
            }
            
          //---ADD NPCs to SCREEN---
          //-----Sub NPC TEST-----
          int newX = player_1.segments.get(0).x - 100;
          int newY = player_1.segments.get(0).y + 100;

          if(newX > (400 + player_1.segments.get(0).x)) newX -= 200;
          if(newX < (player_1.segments.get(0).x - 400)) newX += 200;
          if(newY < 330) newY += 200;
          if(newY > 800) newY -= 200;

          //SANDRAT
           if(seconds > 40 && seconds % 3 == 0 && !tryingToClear)  {
              if((rand.nextInt(200) == 1) || rand.nextInt(800) == 1 && ratCount > 300)
              {
                    //System.out.println("RATCOUNT " + ratCount);
                    npcs.add(new npcSandrat(newX, newY,1,200));
                    counts++;
                    ratCount++;
                    
              }else{
                 ratCount = 0;
              }

           }         
                //GUNNER
             if(seconds > 10 && gameLevel == 1){

                if((counts < 10 && rand.nextInt(200) == 1) || rand.nextInt(800) == 1)
                {
                    //System.out.println("MADE");
                    if(rand.nextInt(2) == 0)
                        npcs.add(new npcPeople(-64,(getSize().height/2),0,100));

                    else
                        npcs.add(new npcPeople(maxWidth+64,(getSize().height/2),1,100));

                    counts++;
                }
            }
              //CAMEL RIDER
            if(seconds > 30 && gameLevel == 1){
                if((counts < 10 && rand.nextInt(200) == 1) || rand.nextInt(800) == 1)
                {
                    if(rand.nextInt(2) == 0)
                        npcs.add(new npcRider(-64,(getSize().height/2),0,100));

                    else
                        npcs.add(new npcRider(maxWidth+64,(getSize().height/2),1,100));

                    counts++;
                }
            }
            //TANK
            if(seconds > 50 && gameLevel == 1)
            {
            	if((counts < 10 && rand.nextInt(300) == 1))
            	{
                    if(rand.nextInt(2) == 0)
                        npcs.add(new npcTank(-64,(getSize().height/2),0,400));
                    else
                        npcs.add(new npcTank(maxWidth+64,(getSize().height/2),1,400));
                    counts++;
            	}
            }

            //Alien
            if(seconds > 0 && gameLevel == 2 && clear)
            {
            	if((counts < 10 && rand.nextInt(250) == 1)|| rand.nextInt(800) == 1)
            	{
                    if(rand.nextInt(2) == 0)
                        npcs.add(new npcAlien(-64,(getSize().height/2),0,200));
                    else
                        npcs.add(new npcAlien(maxWidth+64,(getSize().height/2),1,200));
                    counts++;
            	}
            }


            //ALIAN SHIP
            if(seconds > 50 && gameLevel == 2 && clear)
            {
            	if((counts < 10 && rand.nextInt(250) == 1))
            	{
                    if(rand.nextInt(2) == 0)
                        npcs.add(new npcAlienShip(-64,(getSize().height/2),0,200));
                    else
                        npcs.add(new npcAlienShip(maxWidth+64,(getSize().height/2),1,200));
                    counts++;
            	}
            }

            //MONSTER
            if(seconds > 30 && gameLevel == 2 && clear){
                if((counts < 10 && rand.nextInt(200) == 1) || rand.nextInt(800) == 1)
                {
                    if(rand.nextInt(2) == 0)
                        npcs.add(new npcMonster(-64,(getSize().height/2),0,100));
                    else
                        npcs.add(new npcMonster(maxWidth+64,(getSize().height/2),1,100));
                    counts++;
                }
            }
            
            //ANIMALS
            if(seconds % 2 == 0 && !tryingToClear ){
                if(rand.nextInt(200) == 1&& animal_count > 100)
            	{
                    if(rand.nextInt(2) == 0)
                        npcs.add(new npcAnimals(-64,(getSize().height/2),0,200));

                    else
                        npcs.add(new npcAnimals(maxWidth+64,(getSize().height/2),1,200));

                    counts++;
                    animal_count = 0;
                }else{
                    //System.out.println("Animal Count " + animal_count);
                    animal_count++;
                }
            }

           
            for(int i = 0; i < particles.size(); i++)
            {
                particles.get(i).move(this);
            }

            for(int i = 0; i < bullets.size(); i++)
            {
            	bullets.get(i).action(this, player_1);
            }

            for(int i = 0; i < npcs.size(); i++)
            {
                 npcs.get(i).action(this,player_1);
                
            }

            
            player_1.move(this,upkey, leftkey, rightkey);
            

            repaint();
            try
            {
                Thread.sleep(1000/fps);
            }
            catch(Exception e)
            {

            }
        }
    }

    public void keyPressed(KeyEvent e)
    {
        /*
         * 37 = left arrow
         * 39 = right arrow
         * 40 = down arrow
         * 38 = up arrow
         * 67 = 'C' key
         * 77 = 'M' key
         *    = 'W' key
         *    = 'A' key
         *    = 'S' key
         *    = 'D' key
         */
        if(e.getKeyCode() == 37) // Left arrow
        {
            leftkey = true;
        }
        if(e.getKeyCode() == 39) // Right arrow
        {
            rightkey = true;
        }
        if(e.getKeyCode() == 38) // Up arrow
        {
            upkey = true;
        }
        if(e.getKeyCode() == 84) // 'T' key
        {
            summonToad = true;
        }
        if(e.getKeyCode() == 67) // 'C' key
        {
            player_1.toggleComboMode();
            player_1.comboModeS = "true";
        }
        if(e.getKeyCode() == 77 && !paused) // 'M' key
        {
            if(MC.isActive()) MC.stopMusic();
            else MC.play();
        }
    }
    public void keyReleased(KeyEvent e)
    {
        if(e.getKeyCode() == 37) // Left arrow
        {
            leftkey = false;
        }
        if(e.getKeyCode() == 39) // Right arrow
        {
            rightkey = false;
        }
        if(e.getKeyCode() == 38) // Up arrow
        {
            upkey = false;
        }
        if(e.getKeyCode() == KeyEvent.VK_P)
        {
          
            paused = !paused;

                if(paused) {
                 
                    pauseMenu.captureBG();
                    add(pauseMenu);
                    MC.pause();
                    validate();
                    repaint();
                }
                else {
                   
                    remove(pauseMenu);
                    requestFocusInWindow();
                    MC.play();
                    validate();
                    repaint();
                }
        }
        if(e.getKeyCode() == KeyEvent.VK_F1) {
            toggleMusic =! toggleMusic;

            if(toggleMusic == true) {
                MC.stopMusic();
            }
            else {
                MC.play();
            }
        }

        if(e.getKeyCode() == KeyEvent.VK_F2) {
            MC.stopMusic();
            try {
                MC.changeMusic();
            } catch (MidiUnavailableException ex) {
                Logger.getLogger(Main.class.getName()).log(Level.SEVERE, null, ex);
            } catch (InvalidMidiDataException ex) {
                Logger.getLogger(Main.class.getName()).log(Level.SEVERE, null, ex);
            } catch (IOException ex) {
                Logger.getLogger(Main.class.getName()).log(Level.SEVERE, null, ex);
            }
            MC.play();
        }

        if(e.getKeyCode() == KeyEvent.VK_F3) {
            MC.normalTempo();
        }
    }

    
    public void keyTyped(KeyEvent e)
    {

    }

    @Override
    public void update(Graphics g)
    {
       
        Image screen = createImage(getSize().width,getSize().height);
        Graphics screen_graphics = screen.getGraphics();

        screen_graphics.setColor(new Color(20,131,154));
        screen_graphics.fillRect (0, 0, this.getSize().width, this.getSize().height);
        //screen_graphics.setColor (getForeground());
        
        paint(screen_graphics);
        g.drawImage(screen,0,0,this);

    }
    
    @Override
    public void paint(Graphics g)
    {
        if(getComponentCount() == 0)
        {
            Dimension size = getSize();

            int r = 0;
            if(shaking)
                r = rand.nextInt(shakeamount*2)-shakeamount;

            g.drawImage(skyimg, 0, 0, this);
            ground.draw(g, this);

            for(int i = 0; i < scene.length; i++)
            {
                scene[i].draw(g,this);
            }


            player_1.draw(g,this);         

            for(int i = 0; i < npcs.size(); i++)
            {
            
                npcs.get(i).draw(g,this);
            }

            for(int i = 0; i < particles.size(); i++)
            {
                particles.get(i).draw(g,this);
            }

            for(int i = 0; i < bullets.size(); i++)
            {
                 bullets.get(i).draw(g,this);
            }

            g.setColor(Color.BLACK);
            hud.draw(g,player_1);        
        }
        super.paintComponents(g);

    }

  //added cycle 2
    public void startGame() {

        try{
            MC.stopMenuMusic();
        }
        catch(Exception ex) {

        }
        MC.reset();
        running = true;
        MC.play();
    }

    public Image screenCapture() {
        try
        {
            BufferedImage image  = new Robot().createScreenCapture(
                    new Rectangle(getLocationOnScreen(), new Dimension(800, 600))); //8, 48

            ColorSpace cs = ColorSpace.getInstance(ColorSpace.CS_GRAY);
            ColorConvertOp op = new ColorConvertOp(cs, null);
            image = op.filter(image, null);

            Kernel k = new Kernel(3, 3, new float[] { .1111f, .1111f, .1111f,
                                          .1111f, .1111f, .1111f,
                                          .1111f, .1111f, .1111f });
            ConvolveOp cop = new ConvolveOp(k);
            BufferedImage blurry = cop.filter(image, null);

            /*RescaleOp rop = new RescaleOp(-1.0f, 255f, null);
            BufferedImage negative = rop.filter(blurry, null);
             * This is for the gameover screen
             */

            return blurry;

            } catch (AWTException ex)
            {
                Logger.getLogger(Main.class.getName()).log(Level.SEVERE, null, ex);

            }
        return null;
    }


    public void togglePaused() {
        paused = !paused;
    }

}
